﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MyBlog.Model;
using MyBlog.DataAccess;
using System.Linq.Expressions;
using MyBlog.Common;
using AutoMapper;
using MyBlog.BusinessInterface;
using MyBlog.DataEntity;
using MyBlog.DataAccessInterface;
namespace MyBlog.Business
{
    public class BusinessArticle : IBusinessArticle
    {
        IDALArticle _dalArticle;
        IDALCategory _dalCategory;
        IDALTag _dalTag;
        IUnitOfWork _unitWork;
        public BusinessArticle(IDALArticle dalArticle, IDALCategory dalCategory, IDALTag dalTag, IUnitOfWork unitWork)
        {
            _dalArticle = dalArticle;
            _dalCategory = dalCategory;
            _unitWork = unitWork;
            _dalTag = dalTag;
        }
        public void Add(ArticleModel model)
        {
            var dataEntity = Mapper.Map<Tbl_Article>(model);

            if (model.CategoryIds != null && model.CategoryIds.Length > 0)
            {
                foreach (var id in model.CategoryIds)
                {
                    dataEntity.Tbl_Category.Add(_dalCategory.Get(int.Parse(id)));
                }
            }
            if (!string.IsNullOrWhiteSpace(model.TagStr))
            {
                var tags = model.TagStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Sub(25)).ToArray();
                foreach (var t in tags)
                {
                    var where = LinqExpressionBuilder.True<Tbl_Tag>().And(x => x.TagName.Trim() == t && x.AccountId.ToLower() == dataEntity.AccountId.ToLower());
                    var tg = _dalTag.Get(where);
                    if (tg == null)
                    {
                        var tagnew = new Tbl_Tag { AccountId = model.AccountId, TagName = t };
                        _dalTag.Add(tagnew);
                        dataEntity.Tbl_Tag.Add(tagnew);
                    }
                    else
                    {
                        dataEntity.Tbl_Tag.Add(tg);
                    }
                }
            }
            _dalArticle.Add(dataEntity);
            _unitWork.Commit();
            model.ID = dataEntity.ID;
        }

        public void Update(ArticleModel model)
        {
            var dataEntity = _dalArticle.Get(model.ID);
            dataEntity.Title = model.Title;
            dataEntity.Content = model.Content;
            dataEntity.IsTop = model.IsTop;
            dataEntity.LastUpdateTime = DateTime.Now;
            dataEntity.AllowAnonymous = model.AllowAnonymous;
            dataEntity.AllowComment = model.AllowComment;
            dataEntity.AllowSendIndex = model.AllowSendIndex;
            dataEntity.Profile = model.Profile;
            dataEntity.Tbl_Category.Clear();

            if (model.CategoryIds != null && model.CategoryIds.Length > 0)
            {
                foreach (var id in model.CategoryIds)
                {
                    dataEntity.Tbl_Category.Add(_dalCategory.Get(int.Parse(id)));
                }
            }
            if (!string.IsNullOrWhiteSpace(model.TagStr))//有bug，tag表在清理的时候没有删除
            {
                var tags = model.TagStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Sub(25)).ToArray();
                var oldTags = dataEntity.Tbl_Tag.Select(x => x.TagName).ToArray();
                var expTags = oldTags.Except(tags).Default();
                //对于旧的标签有，新的标签没有，则表示该文章删除了这个标签，需要检查该标签是否还有其他文章引用，如没有则彻底删除该标签
                foreach (var ext in expTags)
                {
                    var where = LinqExpressionBuilder.True<Tbl_Article>().And(x => x.Tbl_Tag.Any(y => y.TagName.Trim() == ext && y.AccountId.ToLower() == dataEntity.AccountId.ToLower()));
                    var arts = _dalArticle.GetAll(where);
                    if (arts.Count == 1)//说明只有当前文章引用这个标签
                    {
                        //可以永久删除标签
                        _dalTag.Delete(arts[0].Tbl_Tag.First(x => x.TagName.Same(ext)).ID);
                    }
                    else//否则只从当前文章删除
                    {
                        dataEntity.Tbl_Tag.Remove(arts[0].Tbl_Tag.First(x => x.TagName.Same(ext)));
                    }
                }
                //对于新的标签有，但旧的标签没有，那就表示该标签是新加的或者是该标签在其他文章出现过，需要新增或关联
                foreach (var item in tags.Except(oldTags).Default())
                {
                    var where = LinqExpressionBuilder.True<Tbl_Tag>().And(x => x.TagName.Trim() == item && x.AccountId.ToLower() == dataEntity.AccountId.ToLower());
                    var tg = _dalTag.Get(where);
                    if (tg == null)
                    {
                        var tagnew = new Tbl_Tag { AccountId = dataEntity.AccountId, TagName = item };
                        _dalTag.Add(tagnew);
                        dataEntity.Tbl_Tag.Add(tagnew);
                    }
                    else
                    {
                        dataEntity.Tbl_Tag.Add(tg);
                    }
                }
            }
            else
            {
                //不再关联标签，则清除该文章全部标签
                dataEntity.Tbl_Tag.Clear();
            }
            _unitWork.Commit();
        }

        public void AddReadOrAgreeCount(int id, ArticleDo opera)
        {
            var dataEntity = _dalArticle.Get(id);
            if (opera == ArticleDo.Read)
            {
                dataEntity.ReadCount++;
            }
            _dalArticle.Update(dataEntity);
            _unitWork.Commit();
        }

        public void AddAgree(int id, string account)
        {
            var dataEntity = _dalArticle.Get(id);
            dataEntity.AgreeUsers = string.IsNullOrWhiteSpace(dataEntity.AgreeUsers) ? account : dataEntity.AgreeUsers + "&" + account;
            _unitWork.Commit();
        }

        public void AddRange(IEnumerable<ArticleModel> models)
        {
            var dataEntitys = Mapper.Map<List<Tbl_Article>>(models);
            _dalArticle.AddRange(dataEntitys);
            _unitWork.Commit();
        }

        public void DeleteRange(IEnumerable<ArticleModel> models)
        {
            var dataEntitys = Mapper.Map<List<Tbl_Article>>(models);
            _dalArticle.DeleteRange(dataEntitys);
            _unitWork.Commit();
        }

        public List<ArticleModel> GetAll(bool isTracking = true)
        {
            var entities = _dalArticle.GetAll(isTracking);
            return Mapper.Map<List<ArticleModel>>(entities);
        }

        public void Delete(params object[] primaryKey)
        {
            var entity = _dalArticle.Get(primaryKey);
            entity.Tbl_Category.Clear();
            entity.Tbl_Tag.Clear();
            _dalArticle.Delete(primaryKey);
            _unitWork.Commit();
        }

        public ArticleModel Get(params object[] primaryKey)
        {
            var dataEntity = _dalArticle.Get(primaryKey);
            return Mapper.Map<ArticleModel>(dataEntity);
        }

        public void Delete(ArticleModel model)
        {
            var where = LinqExpressionBuilder.True<Tbl_Article>();
            if (model.ID > 0)
            {
                where = where.And(x => x.ID == model.ID);
            }
            _dalArticle.Delete(where);
            _unitWork.Commit();
        }

        public ArticleModel Get(ArticleModel model)
        {
            var where = LinqExpressionBuilder.True<Tbl_Article>();
            if (model.ID != 0)
            {
                where = where.And(x => x.ID == model.ID);
            }
            if (!string.IsNullOrWhiteSpace(model.AccountId))
            {
                where = where.And(x => x.AccountId.ToLower() == model.AccountId.ToLower());
            }
            if (!string.IsNullOrWhiteSpace(model.TagStr))
            {
                var tags = model.TagStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                where = where.And(x => x.Tbl_Tag.Any(y => tags.Contains(y.TagName)));
            }
            var dataEntity = _dalArticle.Get(where);
            return Mapper.Map<ArticleModel>(dataEntity);
        }

        public List<ArticleModel> GetAll(ArticleModel model, bool isTracking = true)
        {
            var where = LinqExpressionBuilder.True<Tbl_Article>();
            if (!string.IsNullOrWhiteSpace(model.AccountId))
            {
                where = where.And(x => x.AccountId.ToLower() == model.AccountId.ToLower());
            }
            if (model.CategoryID != 0)
            {
                if (model.CategoryID > 0)
                {
                    where = where.And(x => x.Tbl_Category.Any(y => y.ID == model.CategoryID));
                }
                else
                {
                    where = where.And(x => x.Tbl_Category.Count == 0);
                }
            }
            if (model.QueryDateBegin.HasValue && model.QueryDateBegin.Value != DateTime.MinValue)
            {
                where = where.And(x => x.CreateTime >= model.QueryDateBegin.Value);
            }
            if (model.QueryDateEnd.HasValue && model.QueryDateEnd.Value != DateTime.MinValue)
            {
                where = where.And(x => x.CreateTime <= model.QueryDateEnd.Value);
            }
            if (!string.IsNullOrWhiteSpace(model.TagStr))
            {
                var tags = model.TagStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                where = where.And(x => x.Tbl_Tag.Any(y => tags.Contains(y.TagName)));
            }
            if (model.TagID > 0)
            {
                where = where.And(x => x.Tbl_Tag.Any(y => y.ID == model.TagID));
            }
            var entities = _dalArticle.GetAll(where, isTracking);
            return Mapper.Map<List<ArticleModel>>(entities);
        }

        public List<ArticleModel> GetAll(ArticleModel model, int page, int size, out int total, bool isTracking = true)
        {
            var where = LinqExpressionBuilder.True<Tbl_Article>();
            if (!string.IsNullOrWhiteSpace(model.AccountId))
            {
                where = where.And(x => x.AccountId.ToLower() == model.AccountId.ToLower());
            }
            if (model.CategoryID != 0)
            {
                if (model.CategoryID > 0)
                {
                    where = where.And(x => x.Tbl_Category.Any(y => y.ID == model.CategoryID));
                }
                else
                {
                    where = where.And(x => x.Tbl_Category.Count == 0);
                }
            }
            if (model.QueryDateBegin.HasValue && model.QueryDateBegin.Value != DateTime.MinValue)
            {
                where = where.And(x => x.CreateTime >= model.QueryDateBegin.Value);
            }
            if (model.QueryDateEnd.HasValue && model.QueryDateEnd.Value != DateTime.MinValue)
            {
                where = where.And(x => x.CreateTime <= model.QueryDateEnd.Value);
            }
            if (!string.IsNullOrWhiteSpace(model.TagStr))
            {
                var tags = model.TagStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                where = where.And(x => x.Tbl_Tag.Any(y => tags.Contains(y.TagName)));
            }
            if (model.TagID > 0)
            {
                where = where.And(x => x.Tbl_Tag.Any(y => y.ID == model.TagID));
            }
            var entities = _dalArticle.GetAll(where, page, size, out total, isTracking);
            return Mapper.Map<List<ArticleModel>>(entities);
        }

        public List<Tuple<int, string>> GetArticlePrevAndNext(int aid)
        {
            return _dalArticle.GetArticlePrevAndNext(aid);
        }
    }
}
